<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../Universal.css">
</head>
<body>
    
    <div id="cnblogs_post_body" class="blogpost-body">
        <h2>构造方法</h2>
    <p>我们对封装已经有了基本的了解，接下来我们来看一个新的问题，依然以Person为例，由于Person中的属性都被private了，外界无法直接访问属性，必须对外提供相应的set和get方法。当创建Person对象的时候，Person对象一创建就要明确其姓名和年龄，那该怎么做呢？</p>
    <h3>构造方法介绍</h3>
    <p>在开发中经常需要在创建对象的同时明确对象的属性值，比如员工入职公司就要明确他的姓名、年龄等属性信息。也就是在创建对象的时候就要做的事情，当使用new关键字创建对象时，怎么给对象的属性初始化值呢？这就要学习Java另外一门小技术，构造方法。<br>那什么是构造方法呢？从字面上理解就是对象创建时要执行的方法。既然是对象创建时要执行的方法，那么只要在new对象时，知道其执行的构造方法是什么，就可以在执行这个方法的时候给对象进行属性赋值。</p>
    <p>构造方法的格式：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 0, 1)">修饰符 构造方法名(参数列表)
    {
    }</span></pre>
    </div>
    <h3>构造方法的体现</h3>
    <ul>
    <li>构造方法没有返回值类型。也不需要写返回值。因为它是为构建对象的，对象创建完，方法就执行结束。</li>
    <li>构造方法名称必须和类型保持一致。</li>
    <li>构造方法没有具体的返回值。</li>
    </ul>
    <p>构造方法的代码体现：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Person的成员属性age和name</span>
        <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Person的构造方法，拥有参数列表</span>
        Person(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a, String nm) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 接受到创建对象时传递进来的值，将值赋给成员属性</span>
            age =<span style="color: rgba(0, 0, 0, 1)"> a;
            name </span>=<span style="color: rgba(0, 0, 0, 1)"> nm;
        }
    }</span></pre>
    </div>
    <h3>构造方法调用和内存图解</h3>
    <p>理解构造方法的格式和基本功能之后，现在就要研究构造方法是怎么执行的呢？在创建对象的时候是如何初始化的呢？构造方法是专门用来创建对象的，也就是在new对象时要调用构造方法。现在来看看如何调用构造方法。</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Person的成员属性age和name</span>
        <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Person的构造方法，拥有参数列表</span>
        Person(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a, String nm) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 接受到创建对象时传递进来的值，将值赋给成员属性</span>
            age =<span style="color: rgba(0, 0, 0, 1)"> a;
            name </span>=<span style="color: rgba(0, 0, 0, 1)"> nm;
        }
    
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak() {
            System.out.println(</span>"name=" + name + ",age=" +<span style="color: rgba(0, 0, 0, 1)"> age);
        }
    }
    
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PersonDemo {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 创建Person对象，并明确对象的年龄和姓名</span>
            Person p2 = <span style="color: rgba(0, 0, 255, 1)">new</span> Person(23, "张三"<span style="color: rgba(0, 0, 0, 1)">);
            p2.speak();
        }
    }</span></pre>
    </div>
    <p>上述代码演示了创建对象时构造方法的调用。即在创建对象时，会调用与参数列表对应的构造方法。</p>
    <p>上述代码的图解：</p>
    <p><img src="https://images2015.cnblogs.com/blog/612774/201707/612774-20170713110541853-1233026997.png" alt=""></p>
    <p>图解说明：</p>
    <ul>
    <li>1、首先会将main方法压入栈中，执行main方法中的 new Person(23,"张三");</li>
    <li>2、在堆内存中分配一片区域，用来存放创建的Person对象，这片内存区域会有属于自己的内存地址（0x88）。然后给成员变量进行默认初始化（name=null，age=0）。</li>
    <li>3、执行构造方法中的代码（age = a ; name = nm;）,将变量a对应的23赋值给age，将变量nm对应的”张三赋值给name，这段代码执行结束后，成员变量age和name的值已经改变。执行结束之后构造方法弹栈，Person对象创建完成。将Person对象的内存地址0x88赋值给p2。</li>
    </ul>
    <h3>默认构造方法和细节</h3>
    <p>如果没有显示指定构造方法，当在编译Java文件时，编译器会自动给class文件中添加默认的构造方法。如果在描述类时，我们显示指定了构造方法，那么，当在编译Java源文件时，编译器就不会再给class文件中添加默认构造方法。</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果没有显示指定构造方法，编译会在编译时自动添加默认的构造方法
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Person(){} </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">空参数的默认构造方法</span>
    }</pre>
    </div>
    <p>当在描述事物时，要不要在类中写构造方法呢？这时要根据描述事物的特点来确定，当描述的事物在创建其对象时就要明确属性的值，这时就需要在定义类的时候书写带参数的构造方法。若创建对象时不需要明确具体的数据，这时可以不用书写构造方法（不书写也有默认的构造方法）。</p>
    <p>构造方法的细节：</p>
    <ul>
    <li>1、一个类中可以有多个构造方法，多个构造方法是以重载的形式存在的</li>
    <li>2、构造方法是可以被private修饰的，作用：其他程序无法创建该类的对象。</li>
    </ul>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 私有无参数的构造方法，即外界不能通过new Person();语句创建本类对象</span>
        <span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Person() {
        }
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 多个构造方法是以重载的形式存在</span>
        Person(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a) {
            age </span>=<span style="color: rgba(0, 0, 0, 1)"> a;
        }
    
        Person(String nm, </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a) {
            name </span>=<span style="color: rgba(0, 0, 0, 1)"> nm;
            age </span>=<span style="color: rgba(0, 0, 0, 1)"> a;
        }
    }</span></pre>
    </div>
    <h3>构造方法和一般方法区别</h3>
    <p>构造方法在对象创建时就执行了，而且只执行一次。一般方法是在对象创建后，需要使用时才被对象调用，并可以被多次调用。<br>问题：有了构造方法之后可以对对象的属性进行初始化，那么还需要对应的set和get方法吗？需要相应的set和get方法，因为对象在创建之后需要修改和访问相应的属性值时，在这时只能通过set或者get方法来操作。<br>思考，如下代码有问题吗？</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Person() {//void有问题
        }
    }
    
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PersonDemo {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
            Person p </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
        }
    }</span></pre>
    </div>
    <h2>this关键字</h2>
    <p>在之前学习方法时，我们知道方法之间是可以相互调用的，那么构造方法之间能不能相互调用呢？若可以，怎么调用呢？</p>
    <h3>this调用构造方法</h3>
    <p>在之前学习方法之间调用时，可以通过方法名进行调用。可是针对构造方法，无法通过构造方法名来相互调用。构造方法之间的调用，可以通过this关键字来完成。<br>构造方法调用格式：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">this</span>(参数列表);</pre>
    </div>
    <p>构造方法的调用</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Person的成员属性</span>
        <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 无参数的构造方法</span>
    <span style="color: rgba(0, 0, 0, 1)">    Person() {
        }
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 给姓名初始化的构造方法</span>
    <span style="color: rgba(0, 0, 0, 1)">    Person(String nm) {
            name </span>=<span style="color: rgba(0, 0, 0, 1)"> nm;
        }
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 给姓名和年龄初始化的构造方法</span>
        Person(String nm, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 由于已经存在给姓名进行初始化的构造方法 name = nm;因此只需要调用即可
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 调用其他构造方法，需要通过this关键字来调用</span>
            <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">(nm);
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 给年龄初始化</span>
            age =<span style="color: rgba(0, 0, 0, 1)"> a;
        }
    }</span></pre>
    </div>
    <h3>this的原理图解</h3>
    <p>了解了构造方法之间是可以相互调用，那为什么他们之间通过this就可以调用呢？通过上面的学习，简单知道使用this可以实现构造方法之间的调用，但是为什么就会知道this调用哪一个构造方法呢？接下来需要图解完成。</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        Person() {
        }
        Person(String nm) {
            name </span>=<span style="color: rgba(0, 0, 0, 1)"> nm;
        }
        Person(String nm, </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a) {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">(nm);
            age </span>=<span style="color: rgba(0, 0, 0, 1)"> a;
        }
    }
    
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PersonDemo {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
            Person p </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("张三", 23<span style="color: rgba(0, 0, 0, 1)">);
        }
    }</span></pre>
    </div>
    <p><img src="https://images2015.cnblogs.com/blog/612774/201707/612774-20170713112107400-975118965.png" alt=""></p>
    <p>&nbsp;</p>
    <p>图列说明：</p>
    <ul>
    <li>1、先执行main方法，main方法压栈，执行其中的new Person(“张三”,23);</li>
    <li>2、堆内存中开辟空间，并为其分配内存地址0x33，，紧接着成员变量默认初始化（name=null age = 0）；</li>
    <li>3、拥有两个参数的构造方法（Person（String nm , int a））压栈，在这个构造方法中有一个隐式的this，因为构造方法是给对象初始化的，那个对象调用到这个构造方法，this就指向堆中的那个对象。</li>
    <li>4、由于Person（String nm , int a）构造方法中使用了this(nm);构造方法Person(String nm)就会压栈，并将“张三”传递给nm。在Person（String nm , int a）构造方法中同样也有隐式的this，this的值同样也为0x33，这时会执行其中name = nm，即把“张三”赋值给成员的name。当赋值结束后Person（String nm , int a）构造方法弹栈。</li>
    <li>5、程序继续执行构造方法（Person（String nm , int a）中的age = a；这时会将23赋值给成员属性age。赋值结束构造方法（Person（String nm , int a）弹栈。</li>
    <li>6、当构造方法（Person（String nm , int a）弹栈结束后，Person对象在内存中创建完成，并将0x33赋值给main方法中的p引用变量。</li>
    </ul>
    <h4>this到底代表什么呢？this代表的是对象，具体代表哪个对象呢？哪个对象调用了this所在的方法，this就代表哪个对象。</h4>
    <h4>调用其他构造方法的语句必须定义在构造方法的第一行，原因是初始化动作要最先执行。</h4>
    <h3>成员变量和局部变量同名问题</h3>
    <p>通过上面学习，基本明确了对象初始化过程中的细节，也知道了构造方法之间的调用是通过this关键字完成的。但this也有另外一个用途，当在方法中出现了局部变量和成员变量同名的时候，那么在方法中怎么区别局部变量成员变量呢？可以在成员变量名前面加上this.来区别成员变量和局部变量。</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 给姓名和年龄初始化的构造方法</span>
        Person(String name, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 当需要访问成员变量是，只需要在成员变量前面加上this.即可</span>
            <span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name;
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak() {
            System.out.println(</span>"name=" + <span style="color: rgba(0, 0, 255, 1)">this</span>.name + ",age=" + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.age);
        }
    }
    
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PersonDemo {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
            Person p </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("张三", 23<span style="color: rgba(0, 0, 0, 1)">);
            p.speak();
        }
    }</span></pre>
    </div>
    <h3>this的应用</h3>
    <p>学习完了构造方法、this的用法之后，现在做个小小的练习。需求：在Person类中定义功能，判断两个人是否是同龄人</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 给姓名和年龄初始化的构造方法</span>
        Person(String name, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
    </span><span style="color: rgba(0, 128, 0, 1)">   //</span><span style="color: rgba(0, 128, 0, 1)"> 当需要访问成员变量是，只需要在成员变量前面加上this.即可</span>
            <span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name;
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age;
        }
    
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak() {
            System.out.println(</span>"name=" + <span style="color: rgba(0, 0, 255, 1)">this</span>.name + ",age=" + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.age);
        }
    
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否为同龄人</span>
        <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> equalsAge(Person p) {
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)"> 由于无法确定具体是哪一个对象调用equalsAge方法，这里就可以使用this来代替</span><span style="color: rgba(0, 128, 0, 1)">
        /*</span><span style="color: rgba(0, 128, 0, 1)">
        * if(this.age == p.age) { return true; } return false;
    </span><span style="color: rgba(0, 128, 0, 1)">    */</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> p.age;
        }
    }</span></pre>
    </div>
    <h2>super关键字</h2>
    <p>子父类中构造方法的调用<br>在创建子类对象时，父类的构造方法会先执行，因为子类中所有构造方法的第一行有默认的隐式super();语句。<br>格式：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 0, 1)">//调用本类中的构造方法
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">(实参列表);
    //调用父类中的空参数构造方法
    </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">();
    //调用父类中的有参数构造方法
    </span><span style="color: rgba(0, 0, 255, 1)">super</span>(实参列表);</pre>
    </div>
    <p>为什么子类对象创建都要访问父类中的构造方法？因为子类继承了父类的内容，所以创建对象时，必须要先看父类是如何对其内容进行初始化的，看如下程序：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Test {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
            </span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Zi();
        }
    
    }
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Fu{
        </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> num ;
        Fu(){
            System.out.println(</span>"Fu构造方法"+<span style="color: rgba(0, 0, 0, 1)">num);
            num </span>= 4<span style="color: rgba(0, 0, 0, 1)">;
        }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> Zi <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Fu{
        Zi(){
    </span><span style="color: rgba(0, 128, 0, 1)">    //</span><span style="color: rgba(0, 128, 0, 1)">super(); 调用父类空参数构造方法</span>
            System.out.println("Zi构造方法"+<span style="color: rgba(0, 0, 0, 1)">num);
        }
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">　　执行结果：
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">　　Fu构造方法0
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">　　Zi构造方法4</span></pre>
    </div>
    <p>通过结果发现，子类构造方法执行时中，调用了父类构造方法，这说明，子类构造方法中有一句super()。那么，子类中的构造方法为什么会有一句隐式的super()呢？</p>
    <p>原因：子类会继承父类中的内容，所以子类在初始化时，必须先到父类中去执行父类的初始化动作。这样，才可以使用父类中的内容。<br>当父类中没有空参数构造方法时，子类的构造方法必须有显示的super语句，指定要访问的父类有参数构造方法。</p>
    <h3>子类对象创建过程的细节</h3>
    <p>如果子类的构造方法第一行写了this调用了本类其他构造方法，那么super调用父类的语句还有吗？这时是没有的，因为this()或者super(),只能定义在构造方法的第一行，因为初始化动作要先执行。<br>父类构造方法中是否有隐式的super呢？也是有的。记住：只要是构造方法默认第一行都是super();<br>父类的父类是谁呢？super调用的到底是谁的构造方法呢？Java体系在设计，定义了一个所有对象的父类Object</p>
    <h4>类中的构造方法默认第一行都有隐式的super()语句，用来访问父类中的空参数构造方法。所以父类的构造方法既可以给自己的对象初始化，也可以给自己的子类对象初始化。如果默认的隐式super()语句在父类中没有对应的构造方法，那么必须在构造方法中通过this或者super的形式明确要调用的构造方法。</h4>
    <h3>super应用</h3>
    <p>练习：描述学生和工人这两个类，将他们的共性name和age抽取出来存放在父类中，并提供相应的get和set方法，同时需要在创建学生和工人对象就必须明确姓名和年龄</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">定义Person类，将Student和Worker共性抽取出来</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
        </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> Person(String name, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> super();</span>
            <span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name;
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getName() {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> getAge() {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> age;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> setAge(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age;
        }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> Student <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Person {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Student类的构造方法</span>
        Student(String name, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 使用super关键字调用父类构造方法，进行相应的初始化动作</span>
            <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(name, age);
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> study() {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Studnet中特有的方法</span>
            System.out.println(<span style="color: rgba(0, 0, 255, 1)">this</span>.getName() + "同学在学习"<span style="color: rgba(0, 0, 0, 1)">);
        }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> Worker <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Person {
        Worker(String name, </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 使用super关键字调用父类构造方法，进行相应的初始化动作</span>
            <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(name, age);
        }
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> work() {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Worker 中特有的方法</span>
            System.out.println(<span style="color: rgba(0, 0, 255, 1)">this</span>.getName() + "工人在工作"<span style="color: rgba(0, 0, 0, 1)">);
        }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Test {
        </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
            Student stu </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Student("小明",23<span style="color: rgba(0, 0, 0, 1)">);
            stu.study();
    
            Worker w </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Worker("小李",45<span style="color: rgba(0, 0, 0, 1)">);
            w.work();
        }
    }</span></pre>
    </div>
    <h2>知识点总结</h2>
    <p>this关键字</p>
    <ul>
    <li>this关键字，本类对象的引用</li>
    <li>this是在方法中使用的，哪个对象调用了该方法，那么，this就代表调用该方法的对象引用</li>
    <li>this什么时候存在的？当创建对象的时候，this存在的</li>
    <li>this的作用：用来区别同名的成员变量与局部变量（this.成员变量）</li>
    </ul>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) {
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name;
    }</span></pre>
    </div>
    <p>构造方法： 用来给类的成员进行初始化操作</p>
    <p>格式：</p>
    <div class="cnblogs_code">
    <pre><span style="color: rgba(0, 0, 0, 1)">修饰符 类名 (参数列表) {
        ...
    }</span></pre>
    </div>
    <p>构造方法的特点：</p>
    <ul>
    <li>方法名与类名相同</li>
    <li>没有返回值，也没有返回值类型，连void也没有</li>
    <li>只有在创建对象的时候才可以被调用</li>
    </ul>
    <p>super关键字</p>
    <ul>
    <li>super指的是父类的存储空间(理解为父类的引用)</li>
    <li>调用父类的成员变量：super.成员变量;</li>
    <li>调用父类的构造方法:super(参数);</li>
    <li>调用父类的成员方法:super.成员方法();</li>
    </ul>
    <p>继承中的构造方法注意事项：</p>
    <ul>
    <li>如果我们手动给出了构造方法，编译器不会在给我们提供默认的空参数构造方法</li>
    <li>如果我们没写任何的构造方法，编译器提供给我们一个空参数构造方法</li>
    <li>在构造方法中，默认的第一条语句为 super();它是用来访问父类中的空参数构造方法，进行父类成员的初始化操作</li>
    <li>当父类中没有空参数构造方法的时候，&nbsp;可以通过 super(参数) 访问父类有参数的构造方法；&nbsp;也可以通过 this(参数) 访问本类中其他构造方法，前提是本类中的其他构造方法已经能够正常访问父类构造方法；</li>
    <li>super(参数) 与 this(参数) 不能同时在构造方法中存在。</li>
    </ul>
    </div>

</body>
</html>